//
//  KLMSmartGroup.swift
//  KLM
//
//  Created by 朱雨 on 2021/7/20.
//

import UIKit
import nRFMeshProvision
import JKSwiftExtension

enum GroupType {
    case same ///同类型
    case different ///不同类型
    case sceneRecognition ///场景识别
}

class KLMSmartGroup: NSObject {
    
    static let sharedInstacnce = KLMSmartGroup()
    private override init(){
        super.init()
        
    }
    
    typealias SuccessBlock = (_ source: Address?) -> Void
    typealias FailureBlock = (_ error: MessageError?) -> Void
    
    var successBlock: SuccessBlock?
    var failureBlock: FailureBlock?
    
    ///分组 send
    func sendMessage(_ parame: parameModel, toGroup group: Group, isCanInternet: Bool? = true, _ success: @escaping SuccessBlock, failure: @escaping FailureBlock) {
        
        if group.allNode().count == 0 {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("No devices")
            err.code = -1
            failure(err)
            return
        }
        
        let parameString = parame.value!
        let dpString = parame.dp!.rawValue.decimalTo2Hexadecimal()
        
//        if isCanInternet == true && KLMRemoteManager.shared.isRemote {
//            let opCode = "DAFF00"
//            KLMService.remoteControlDevice(groupControl: 1, groupId: group.address.address, opCode: opCode, dpCode: dpString, cfgInfo: parameString) { response in
//                success(nil)
//            } failure: { error in
//                let err = MessageError()
//                err.message = error.localizedDescription
//                failure(err)
//            }
//            return
//        }
                
        //蓝牙没开启
        do {
            try KLMConnectManager.checkBluetoothState()
            
        } catch {
            
            if let errr = error as? MessageError {
                failure(errr)
                return
            }
        }
        //一个设备都没连接
        if !MeshNetworkManager.bearer.isOpen {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("Make sure the device is powered on and near your device.")
            failure(err)
            return
        }
        
        if let opCode = UInt8("1A", radix: 16) {
            let parameters = Data(hex: dpString + parameString)
            KLMLog("parameter = \(parameters.hex)")
            let network = MeshNetworkManager.instance.meshNetwork!
            let models = network.models(subscribedTo: group)
            if let model = models.first {
                
                let message = RuntimeVendorMessage(opCode: opCode, for: model, parameters: parameters)
                do {
                    
                    try MeshNetworkManager.instance.send(message, to: group, using: model.boundApplicationKeys.first!)
                    success(nil)
                    
                } catch {
                    
                    let err = MessageError()
                    err.message = error.localizedDescription
                    failure(err)
                    
                }
            }
        }
    }
    
    /// 给所有节点发消息
    /// - Parameters:
    ///   - parame: 参数
    ///   - success: success
    ///   - failure: failure
    func sendMessageToAllNodes(_ parame: parameModel, isCanInternet: Bool? = true, _ success: @escaping SuccessBlock, failure: @escaping FailureBlock) {
        
        if KLMSmartGroup.allNodes().count == 0 {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("No devices")
            failure(err)
            return
        }
        
        let parameString = parame.value!
        let dpString = parame.dp!.rawValue.decimalTo2Hexadecimal()
        
//        if isCanInternet == true && KLMRemoteManager.shared.isRemote {
//            let opCode = "DAFF00"
//            KLMService.remoteControlDevice(groupControl: 1, groupId: 0, opCode: opCode, dpCode: dpString, cfgInfo: parameString) { response in
//                success(nil)
//            } failure: { error in
//                let err = MessageError()
//                err.message = error.localizedDescription
//                failure(err)
//            }
//            return
//        }
        
        do {
            try KLMConnectManager.checkBluetoothState()
            
        } catch {
            
            if let errr = error as? MessageError {
                failure(errr)
                return
            }
        }
        
        //一个设备都没连接
        if !MeshNetworkManager.bearer.isOpen {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("Make sure the device is powered on and near your device.")
            failure(err)
            return
        }
        
        
        if let opCode = UInt8("1A", radix: 16) {
            let parameters = Data(hex: dpString + parameString)
            KLMLog("parameter = \(parameters.hex)")
            
            let network = MeshNetworkManager.instance.meshNetwork!
            let notConfiguredNodes = network.nodes.filter({ !$0.isConfigComplete && !$0.isProvisioner })
            guard !notConfiguredNodes.isEmpty else {
                return
            }
            
            ///可能节点没配置完成
            guard let model = KLMHomeManager.getModelFromNode(node: notConfiguredNodes.first!), model.boundApplicationKeys.first != nil else {
                let err = MessageError()
                err.message = KLMLocalizable.LANGLOC("model not bound to Appkey")
                failure(err)
                return
            }
            let message = RuntimeVendorMessage(opCode: opCode, for: model, parameters: parameters)
            do {
                //allNodes 为所有节点
                try  MeshNetworkManager.instance.send(message, to: MeshAddress.init(.allNodes), using: model.boundApplicationKeys.first!)
                success(nil)
                
            } catch {
                
                let err = MessageError()
                err.message = error.localizedDescription
                failure(err)
                
            }
        }
    }
    
    ///分组 read
    func readMessage(toGroup group: Group, isCanInternet: Bool? = true, _ success: @escaping SuccessBlock, failure: @escaping FailureBlock) {
        
        if group.allNode().count == 0 {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("No devices")
            err.code = -1
            failure(err)
            return
        }
        
//        if isCanInternet == true && KLMRemoteManager.shared.isRemote {
//            success(nil)
//            return
//        }
        
        do {
            try KLMConnectManager.checkBluetoothState()
            
        } catch {
            
            if let errr = error as? MessageError {
                failure(errr)
                return
            }
        }
        
        //一个设备都没连接,  群组发送消息也可以发送出去，没报异常。所以要添加这个
        if !MeshNetworkManager.bearer.isOpen {
            let err = MessageError()
            err.message = KLMLocalizable.LANGLOC("Make sure the device is powered on and near your device.")
            failure(err)
            return
        }
        
        success(nil)
    }
}

extension KLMSmartGroup {
    
    ///判断两个设备是否是同种类型的设备
    static func isThesametype(first: Node, secode: Node) -> Bool {
        var isSame = false
        if first.controlType == secode.controlType {
            isSame = true
        }
        
        if isSame == false {
            SVProgressHUD.showInfo(withStatus: KLMLocalizable.LANGLOC("Same type only"))
        }
        return isSame
    }
    ///所有设备的控制类型
    static func allDeviceType() -> ControlType {
        var type: ControlType = .none
        if let network = MeshNetworkManager.instance.meshNetwork {
            
            let notConfiguredNodes = network.nodes.filter({ !$0.isConfigComplete && !$0.isProvisioner})
            if notConfiguredNodes.count <= 0 {
                return .none
            }
            if notConfiguredNodes.contains(where: {$0.controlType == .RGBlight}) {
                return .RGBlight
            }
            
            let node = notConfiguredNodes[0]
            if notConfiguredNodes.allSatisfy({ $0.controlType == node.controlType}) {
                type = node.controlType
            }
        }
        return type
    }
    ///所有设备
    static func allNodes() -> [Node] {
        if let network = MeshNetworkManager.instance.meshNetwork {
            let notConfiguredNodes = network.nodes.filter({ !$0.isConfigComplete && !$0.isProvisioner})
            return notConfiguredNodes
        }
        return [Node]()
    }
}

extension Group {
    
    ///获取分组中的某个设备
    func nodeIndex(index: Int) -> Node? {
        let network = MeshNetworkManager.instance.meshNetwork!
        let models = network.models(subscribedTo: self)
        if let model = models.indexValue(safe: index) {
            let node = KLMHomeManager.getNodeFromModel(model: model)
            return node
        }
        return nil
    }
    
    ///获取分组中的所有设备
    func allNode() -> [Node] {
        var nodes = [Node]()
        let network = MeshNetworkManager.instance.meshNetwork!
        let models = network.models(subscribedTo: self)
        for model in models {
            let node = KLMHomeManager.getNodeFromModel(model: model)
            nodes.append(node!)
        }
        return nodes
    }
    
    ///分组的控制类型
    func controlType() -> ControlType {
        var type: ControlType = .none
        if self.type() == .same {
            if let node = nodeIndex(index: 0) {
                type = node.controlType
            }
        }
        return type
    }
    ///分组的类型
    func type() -> GroupType {
        switch groupType {
        case 1:
            return .different
        case 2:
            return .sceneRecognition
        default:
            return .same
        }
    }
    ///分组图标
    var icon: String {
        switch type() {
        case .different:
            return "icon_group_different"
        case .sceneRecognition:
            return "icon_RK"
        default:
            return "icon_group_same"
        }
    }
}

extension KLMSmartGroup {
    ///根据分组地址获取分组
    static func getGroupFromAddress(address: Address?) -> Group? {
        guard let address = address else { return nil }
        let meshAddress = MeshAddress.init(address)
        return MeshNetworkManager.instance.meshNetwork?.group(withAddress: meshAddress)
    }
}

